home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / answrbok / 8_5.lha / 8_5 / doprint.c < prev    next >
C/C++ Source or Header  |  1993-08-08  |  3KB  |  139 lines

  1. * Copyright (c) 1990 by AT&T Bell Telephone Laboratories, Incorporated. */
  2. * The C++ Answer Book */
  3. * Tony Hansen */
  4. * All rights reserved. */
  5. / _doprint(): low level function for doing
  6. / formatted output, to be invoked by the
  7. / v*printf() family of functions
  8. include <string.h>
  9.  
  10. / endchar() returns TRUE for those format
  11. / characters which cause output.
  12. nt endchar(char c)
  13.  
  14.    switch (c)
  15. {
  16. case 'd': case 'i': case 'o': case 'u':
  17. case 'x': case 'X': case 'f': case 'e':
  18. case 'E': case 'g': case 'G': case 'c':
  19. case 's': case 'p': case 'n': case '%':
  20. case 0:
  21.     return 1;
  22.  
  23. default:
  24.     return 0;
  25. }
  26.  
  27.  
  28. nt _doprint(ostream *out, const char *fmt, va_list vl)
  29.  
  30.    if (!fmt)
  31. return EOF;
  32.  
  33.    char *cfmt = new char[strlen(fmt)+1];
  34.  
  35.    while (*fmt)
  36. {
  37. char *buf = cfmt;
  38. int asterisks = 0;
  39. int shortarg = 0;
  40. int longarg = 0;
  41. char c;
  42.  
  43. // loop looking for the beginning of a format
  44. while ((c = *buf++ = *fmt++) && (c != '%'))
  45.     ;
  46.  
  47. // loop looking for the end of the format
  48. if (c)
  49.     while (!endchar(c = *buf++ = *fmt++))
  50.     if (c == '*')        asterisks++;
  51.     else if (c == 'h')    shortarg++;
  52.     else if (c == 'l')    longarg++;
  53.  
  54. // polish off the buffer. leave fmt
  55. // pointing at the null if just past it.
  56. *buf = '\0';
  57. if (!c)
  58.     fmt--;
  59.  
  60. // pull off the width and precision
  61. int prec = 0, width = 0;
  62. switch (asterisks)
  63.     {
  64.     case 0: break;
  65.     case 2: width = va_arg(vl, int); // NO BREAK
  66.     case 1: prec  = va_arg(vl, int); break;
  67.     }
  68.  
  69. / Declare a generic output routine for the type passed
  70. / on the stack and the type used for output. This
  71. / cannot be an inline since the parameters are types.
  72. define OUTPUT(parmtype, outtype)            \
  73.    do {                        \
  74.    outtype val = va_arg(vl, parmtype);            \
  75.    switch (asterisks)                    \
  76. {                        \
  77. case 0:                     \
  78.     (*out) << form(cfmt, val); break;        \
  79. case 1:                        \
  80.     (*out) << form(cfmt, prec, val); break;    \
  81. case 2:                        \
  82.     (*out) << form(cfmt,width,prec,val);break;    \
  83. }                        \
  84.    } while (0)
  85.  
  86. // extract the value and output it
  87. switch (c)
  88.     {
  89.     // decimal variables
  90.     case 'd': case 'i':
  91.     if (longarg)
  92.         OUTPUT(long, long);
  93.  
  94.     else if (shortarg)
  95.         OUTPUT(short, int);
  96.  
  97.     else
  98.         OUTPUT(int, int);
  99.     break;
  100.  
  101.     // unsigned decimal variables
  102.     case 'o': case 'u': case 'x': case 'X':
  103.     if (longarg)
  104.         OUTPUT(unsigned long, unsigned long);
  105.  
  106.     else if (shortarg)
  107.         OUTPUT(unsigned short, unsigned int);
  108.  
  109.     else
  110.         OUTPUT(unsigned int, unsigned int);
  111.     break;
  112.  
  113.     // double variables
  114.     case 'f': case 'e': case 'E':
  115.     case 'g': case 'G':
  116.     OUTPUT(double, double);
  117.     break;
  118.  
  119.     // character variables
  120.     case 'c':
  121.     OUTPUT(unsigned char, int);
  122.     break;
  123.  
  124.     // string variable
  125.     case 's':
  126.     OUTPUT(char*, char*);
  127.     break;
  128.  
  129.     // nothing much here
  130.     case '%': case 0:
  131.     (*out) << form(cfmt);
  132.     break;
  133.     }
  134. }
  135.  
  136.    delete cfmt;
  137.    return 1;
  138.  
  139.